﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Arbore;
using Operators;
using Satates;
using Common;

namespace Algorithms.LDepthStrategy
{
    public class LDepthSearchAlgo : Algorithm
    {
        Arbore.Arbore ab;
        public LDepthSearchAlgo(State iState, List<State> fStates, List<iOperator> opr, List<string> log,
          ref Arbore.Arbore Ab)
            : base(iState, fStates, opr, log)
        {
            ab = Ab;
        }

        private bool switcher;
        private iOperator last;
        private int maxDepth;
        private int currentDepth;
        private bool result = false;
        private bool finished = false;

        private bool expand(State thisState)
        {
            int counter = 0;
            if (switcher==true)
            {
                counter = getIndex(thisState.RedoOperator) + 1; switcher=false;
            }
            if (getIndex(thisState.CurrentOperator) == operatorNumber && currentDepth > maxDepth) { if (OTest())finished = true; last = btStack.Peek().RedoOperator; counter = 0; }
            Nod a = ab.CurrentNod; 
            for (int i = counter; i <= operatorNumber; i++)
            {
                if (operators.ElementAt(i).available(thisState.CurrentState))
                {
                    var m = (Template)thisState.CurrentState.Clone();
                    State auxiliary = new State(operators.ElementAt(i).execute(m), operators.ElementAt(i));
                    ab.CurrentNod = a;
                    ab.AddS(new Nod(operators.ElementAt(i).ToString() + Environment.NewLine + auxiliary.ToString()));
                    if (!found(auxiliary))
                    {
                        btStack.Push(auxiliary);
                       
                        currentDepth++; return true;
                    }
                }
            }
            return false;
        }

        private bool OTest()
        {
            if (last != null)
                if (last.Equals(btStack.Peek().RedoOperator))
                {
                    return true;
                }

            return false;
        }



        private bool solve(State thisState)
        {

            if (switcher==false) switcher=false;
            if (thisState != null && finished == false)
            {
                if (expand(thisState) && currentDepth <= maxDepth)
                {
                    if (solutionFound(btStack.Peek())) { result = true; return true; };
                }
                else
                {
                    iOperator auxiliaryOperator = btStack.Peek().CurrentOperator;
                    if (btStack.Count() > 1)
                        btStack.Pop();
                    State auxiliaryState = btStack.Peek();
                    btStack.Pop();
                    auxiliaryState.RedoOperator=auxiliaryOperator;
                    btStack.Push(auxiliaryState);
                    switcher=true;
                    currentDepth--;
                }
                solve(btStack.Peek());
            }
            return false;
        }




        public override bool solveProblem()
        {
            ab.AddS(new Nod(initialState.ToString()));
            result = false;
            solve(initialState);
            if (result == true) return true;
            return false;

        }
        public override void init()
        {
            currentDepth = 1;
            switcher = false;
        }

        public void setMaxDepth(int maxDepth)
        {
            this.maxDepth = maxDepth;
        }

        public int getMaxDepth()
        {
            return maxDepth;
        }	


    }
}
